/**
 * 
 */
package com.swg.cocobox.filetransfer;

import java.io.File;
import java.io.IOException;
import java.nio.channels.SocketChannel;

import com.swg.cocobox.filetransfer.command.ClientCommand;
import com.swg.cocobox.filetransfer.command.CommandContext;
import com.swg.cocobox.filetransfer.command.CommandContext.CommandEncoding;
import com.swg.cocobox.filetransfer.command.CommandEvent;
import com.swg.cocobox.filetransfer.command.ReplyCommand;
import com.swg.cocobox.filetransfer.command.ReplyCommandFactory;
import com.swg.cocobox.filetransfer.data.TransferRequest;

/**
 * @author satriaprayoga
 *
 */
final public class CommandDispatcherHelper {
	
	private CommandDispatcherHelper(){}
	
	private static ClientCommandDispatcherFactory dispatcherFactory=null;
	
	private static final ReplyCommandFactory replyCommandFactory=CommandContext.getReplyCommandFactory(CommandEncoding.ASCII);
	
	public static ClientCommandDispatcherFactory getBuiltinDispatcherFactory(){
		if(dispatcherFactory==null){
			dispatcherFactory=new SimpleActionDispatcherFactory();
		}
		return dispatcherFactory;
	}
	
	private static class SimpleActionDispatcherFactory implements ClientCommandDispatcherFactory{

		@Override
		public ClientCommandDispatcher createDispatcher(ClientCommand command) {
			String commandCode=command.getCommandCode();
			if(commandCode.equals(CommandContext.CWD)){
				return new CwdActionDispatcher();
			}else if(commandCode.equals(CommandContext.RETR)){
				return new RetrActionDispatcher();
			}else if(commandCode.equals(CommandContext.LPTR)){
				return new LptrActionDispatcher();
			}else{
				return new UnknownActionDispatcher();
			}
		}
		
	}

	private static class CwdActionDispatcher extends ClientCommandDispatcher{
		public CwdActionDispatcher() {
			super(CommandContext.CWD);
		}

		@Override
		public void dispatch(FileServer server, SocketChannel channel,
				ClientCommand command) throws IOException {
		}
		
	}
	
	private static class RetrActionDispatcher extends ClientCommandDispatcher{

		public RetrActionDispatcher() {
			super(CommandContext.RETR);
		}

		@Override
		public void dispatch(FileServer server, SocketChannel channel,
				ClientCommand command) throws IOException {
			File file=new File(command.getMessage());
			if(file.exists()){
				ReplyCommand replyCommand=replyCommandFactory.createReply(CommandContext.COMMAND_OK, command.getMessage());
				CommandEvent event=server.getEventSupport().fireEvent(channel, replyCommand);
				server.getEventProcessor().queueEvent(event);
			}
			
		}
	}
	
	private static class LptrActionDispatcher extends ClientCommandDispatcher{
		public LptrActionDispatcher() {
			super(CommandContext.LPTR);
		}
		
		@Override
		public void dispatch(FileServer server, SocketChannel channel,
				ClientCommand command) throws IOException {
			File file=new File(command.getMessage());
			ReplyCommand replyCommand=replyCommandFactory.createReply(CommandContext.FILE_STATUS_OK, command.getMessage()+" "+file.length());
			CommandEvent event=server.getEventSupport().fireEvent(channel, replyCommand);
			server.getEventProcessor().queueEvent(event);
			
			TransferRequest request=new TransferRequest();
			request.setDestAddress(channel.socket().getInetAddress());
			request.setPort(CommandContext.DEFAULT_DATAPORT);
			request.setRequestedFile(file);
			server.getDataTransfer().transfer(request);
			
		}
	}
	
	private static class UnknownActionDispatcher extends ClientCommandDispatcher{
		public UnknownActionDispatcher() {
			super("UNKNOWN");
		}
		@Override
		public void dispatch(FileServer server, SocketChannel channel,
				ClientCommand command) throws IOException {
			ReplyCommand replyCommand=replyCommandFactory.createReply(CommandContext.UNKNOWN_COMMAND, "unknown");
			CommandEvent event=server.getEventSupport().fireEvent(channel, replyCommand);
			server.getEventProcessor().queueEvent(event);
			
		}
	}
}
